<template>
  <pre v-html="str" class="show-json"></pre>
</template>

<script>
export default {
  props: {
    data: {
      default: () => ({})
    }
  },
  watch: {
    data () {
      this.filterData(this.data)
    }
  },
  created () {
    this.filterData(this.data)
  },
  data () {
    return {
      str: ''
    }
  },
  methods: {
    filterData (data) {
      let json = JSON.parse(JSON.stringify(data))

      if (typeof json != 'string') {
        json = JSON.stringify(json, undefined, 2)
      }
      json = json
        .replace(/&/g, '&')
        .replace(/</g, '<')
        .replace(/>/g, '>')
      const htmlStr = json.replace(
        /('(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\'])*'(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, // eslint-disable-line
        function (match) {
          var cls = 'show-json-number'
          if (/^'/.test(match)) {
            if (/:$/.test(match)) {
              cls = 'show-json-key'
            } else {
              cls = 'show-json-string'
            }
          } else if (/true|false/.test(match)) {
            cls = 'show-json-boolean'
          } else if (/null/.test(match)) {
            cls = 'show-json-null'
          }
          return `<span class="${cls}">${match}</span>`
        }
      )

      this.str = htmlStr
    }
  }
}
</script>

<style lang="scss" scoped>
  .show-json {
    outline: 1px solid #ccc;
    padding: 5px;
    margin: 5px;
    overflow: auto;
  }
</style>
